feat: intent-swap extension — solve signed Fusion orders for same-block inclusion#1
Open
kayibal wants to merge 6 commits into
Open
feat: intent-swap extension — solve signed Fusion orders for same-block inclusion#1kayibal wants to merge 6 commits into
kayibal wants to merge 6 commits into
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
kayibal
force-pushed
the
feat/intent-swap
branch
from
July 22, 2026 10:48
70c2836 to
a053c79
Compare
Add an optional, non-blocking stream of block-build lifecycle events so in-process services can observe block construction as it happens. BuildEventEmitter owns an optional mpsc sender and is held as Arc<BuildEventEmitter> on the payload builder and its context, built in service.rs and mirroring the existing ws_pub / rejected_tx_sender wiring. Emission uses try_send and never blocks building: a full channel drops the event (backpressure), and a closed channel — the consumer having gone away — warns once per emitter rather than on every subsequent transaction. The payload builder emits four events per job, correlated by payload id: IterationStart, one TxExecuted per committed transaction (carrying its receipt logs), and a terminal IterationComplete or IterationAborted. When no consumer is attached the emitter is a no-op and BuilderConfig carries only the Option<BuildEventSender> wiring handle as data. A driver test asserts the full event sequence and single-payload-id correlation for a built block. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce the base-intent-swap crate: an in-process service that accepts signed 1inch Fusion orders and (in later commits) settles them into the current block. This commit adds the RPC ingress and configuration. intent_submitOrder validates order shape and the Dutch-auction window and enqueues accepted orders; it deliberately does not recover the maker's EIP-712 signature — the on-chain LOP validates it, and an optional pre-flight (IntentSwapConfig::verify_onchain_taking, default off) can reject unfillable orders before signing. Distinct error codes cover malformed signature, expired auction, invalid order, a full intake queue, and an unavailable engine. The EOA signing key is redacted from Debug. The solver engine is the backrunner crate, consumed as a git dependency pinned by rev to builder-integration main. The tycho / fynd stack it pulls in pins tycho-common/-simulation/-execution at 0.305.1 in Cargo.lock; these are load-bearing, as fynd-core 0.81.1 does not compile against the newer 0.339.x line, so the lockfile must not be regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the engine task: it consumes the build-event stream to track the in-progress block and, on each submitted order, solves it against committed state overlaid with that block's executed transactions, signs the resulting settlement, and inserts it into the txpool for same-block inclusion. The iteration state machine attributes TxExecuted events by payload id, so a stale event from a superseded payload job cannot pollute the current overlay. At block seal or abort the accumulated transactions are cleared: the sealed block's transactions become committed state and must not be double-counted, and an aborted job's transactions never landed — so orders arriving between blocks solve against last committed state. The settlement nonce is read from the pool's highest transaction for the signer per candidate (chaining locally within a candidate) rather than a counter that could permanently desync from pool state. The settlement stays a typed Recovered<BaseTransactionSigned> from signing through insertion, recovering the signer from the transaction itself instead of trusting a separately-threaded address. Inclusion is reported by observing the builder's own settlement transactions in the event stream, distinct from pool acceptance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire the intent-swap service into the builder. IntentSwapExtension registers the intent_ RPC namespace and, on node start, spawns the engine task with a handle to the txpool. If the engine fails to start it panics rather than returning: reth's critical-task fail-fast only triggers on panic, and a silently dead engine behind a running builder is worse than a restart. A --builder.intent-swap.* CLI group (disabled by default) configures the service; the flag parsing lives in the builder binary so the cli crate gains no new dependencies. With the extension disabled the builder behaves exactly as before — no channel is created and no events are emitted. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document running the service against Base in non-proposing (shadow) mode — the builder has no built-in shadow flag, so the runbook covers driving it via op-node / forkchoice replay — and record the load-bearing Cargo.lock pins (fynd-core 0.81.1's open tycho ranges do not build against 0.339.x). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kayibal
force-pushed
the
feat/intent-swap
branch
from
July 22, 2026 11:53
a053c79 to
2c18f8d
Compare
The order_id was accepted as any non-empty string even though it claims to be the order's EIP-712 digest, so spoofed or garbage ids flowed into logs and RPC responses unchecked. Reject anything that is not 0x plus 64 hex chars with INVALID_ORDER. This is a format check only. Deriving the digest server-side and ignoring the client-supplied value entirely belongs to the maker-sig verification follow-up, which already computes it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an in-process intent-swap service to the Base builder. Signed 1inch Fusion orders arrive over a new
intent_submitOrderRPC, are solved on arrival against committed AMM state overlaid with the transactions the builder has executed so far in the in-progress block, and the signed settlement is inserted into the builder's txpool for same-block inclusion. Settlement uses the existing Fusion resolver contracts; the solver is thebackrunnercrate (Tycho state + Fynd routing), consumed as a git dependency.This is a proof of concept, intended to derive concrete requirements for the feature — see Limitations.
Reading guide (commits in order)
feat(builder-core): stream block-build lifecycle events— an optional, non-blocking build-event stream from the flashblocks payload builder (BuildEventEmitter, held likews_pub). No effect when no consumer is attached. Isolated to builder-core.feat(intent-swap): add crate with intent_submitOrder RPC and config— the newbase-intent-swapcrate: RPC ingress, validation, config, and the engine dependency pin.feat(intent-swap): solve submitted orders against pending state— the engine: solve-on-arrival, pending-state overlay, pool-derived nonce, typed settlement, inclusion telemetry.feat(intent-swap): node extension, CLI flags, and builder wiring— theBaseNodeExtension,--builder.intent-swap.*flags (off by default), bin wiring.docs(intent-swap): usage and Base-shadow runbook.Notes for reviewers
--builder.intent-swap.enabledoff, the builder is unchanged — no channel, no events, no extension.verify_onchain_taking, off by default) can reject unfillable orders before signing.Debugoutput.Testing
base-intent-swap: RPC validation paths, uuid derivation, sign→recover roundtrip, config redaction.base-builder-core: driver test asserting the build-event sequence and single-payload-id correlation.cargo check+clippy -D warnings+fmtclean on builder-core, intent-swap, cli, and the builder bin.Build notes
Cargo.lockpinstycho-common/-simulation/-executionat 0.305.1 deliberately:fynd-core0.81.1 does not compile against the 0.339.x line. Do not regenerate the lockfile.Limitations / out of scope (PoC)
revm. It compiles and links (the engine↔builder boundary is plain data, so the tworevmversions never meet at a type boundary), butcargo deny check bansflags the duplicates. Resolving this means either an out-of-process/sidecar deployment or upgrading the tycho stack to Base'srevmgeneration — deferred.🤖 Generated with Claude Code